

#include <scene.h>
#include <gfx/istaticmesh.h>
#include <physics/physicsshapegenerator.h>

ManualLevelOfDetailSolver::ManualLevelOfDetailSolver ()
  : iLevelOfDetailSolver ()
  , _num (0)
  , _entry (0)
{
  CE_OBJECT_CONSTR;
}

void ManualLevelOfDetailSolver::SetNum(unsigned num)
{
  _num = num;
}

unsigned ManualLevelOfDetailSolver::GetNum() const
{
  return _num;
}

void ManualLevelOfDetailSolver::SetEntry(unsigned entry)
{
  _entry = entry;
}

unsigned ManualLevelOfDetailSolver::GetEntry() const
{
  return _entry;
}

unsigned ManualLevelOfDetailSolver::Solve(unsigned numStages, float distance) const
{
  return _entry;
}

Geometry::Geometry (iMesh *mesh, Material *material)
  : ceGeometry (mesh, 0)
  , _triMeshShape (0)
{
  CE_OBJECT_CONSTR;

  SetMetaMaterial(material);
}

Geometry::~Geometry()
{
  ReleaseTriangleMeshCollisionShape();
}


void Geometry::SetMetaMesh(ceMeshType type, const QString &filename)
{
  _meshFilename = filename;
  _meshType = type;
}


void Geometry::SetMetaMaterial(Material* material)
{
  _material = material;
  if (_material)
    {
      ceGeometry::SetMaterial(material->GetMaterial());
    }
  else
    {
      ceGeometry::SetMaterial((ceMaterial*)0);
    }
}


const QString& Geometry::GetMetaMeshFilename() const
{
  return _meshFilename;
}

ceMeshType Geometry::GetMetaMeshType() const
{
  return _meshType;
}

QString Geometry::GetMetaMaterialName() const
{
  if (!_material)
    {
      return "";
    }

  QString name = _material->GetCategory().GetFullName() + "." + _material->GetExportName();
  return name;
}


btTriangleMeshShape* Geometry::GetTriangleMeshCollisionShape()
{
  if (!_triMeshShape)
    {
      switch (_meshType)
        {

        case MT_Static:
          do
            {
              iStaticMesh* staticMesh = static_cast<iStaticMesh*>(GetMesh());
              _triMeshShape = cmPhysicsShapeGenerator::CreateTriMeshShape(staticMesh->GetMesh());
            }
          while (false);
          break;

        default:
          _triMeshShape = 0;
          break;
        }
    }

  return _triMeshShape;
}

void Geometry::ReleaseTriangleMeshCollisionShape()
{
  if (!_triMeshShape)
    {
      return;
    }

  btStridingMeshInterface* smi = _triMeshShape->getMeshInterface();
  if (smi)
    {
      delete smi;
    }

  delete _triMeshShape;
  _triMeshShape = 0;

}


LODNode::LODNode ()
  : ceLODNode ()
  , EditorSceneNode (NodeType_LODNode)
	, _solver (new ManualLevelOfDetailSolver ())
{

	_solver->AddRef ();

  Get ().SetSolver(_solver);
}

LODNode::~LODNode ()
{
	CE_UNSET(_solver);
}


ManualLevelOfDetailSolver* LODNode::GetSolver()
{
  return _solver;
}


EditorSceneNode::EditorSceneNode (NodeType type)
  : _selectable (true)
  , _selected (false)
  , _composition (false)
{
}

EditorSceneNode* EditorSceneNode::FromNode(ceNode *node)
{
  switch (node->GetType())
    {
    case NT_EntityNode:
      {
        ceEntityNode* ceen = static_cast<ceEntityNode*>(node);
        EntityNode* en = static_cast<EntityNode*>(ceen);
        return static_cast<EditorSceneNode*>(en);
      }
      break;

    case NT_GroupNode:
      {
        ceGroupNode* cegn = static_cast<ceGroupNode*>(node);
        GroupNode* gn = static_cast<GroupNode*>(cegn);
        return static_cast<EditorSceneNode*>(gn);
      }
      break;

    case NT_LODNode:
      {
        ceLODNode* celodn = static_cast<ceLODNode*>(node);
        LODNode* lodn = static_cast<LODNode*>(celodn);
        return static_cast<EditorSceneNode*>(lodn);
      }
      break;

    }

  return 0;
}

bool EditorSceneNode::IsSelectable() const
{
  return _selectable;
}

void EditorSceneNode::SetSelectable(bool selectable)
{
  _selectable = selectable;
  SetSelected(_selected);
}

bool EditorSceneNode::IsSelected() const
{
  return _selected;
}

void EditorSceneNode::SetSelected(bool selected)
{
  _selected = selected && _selectable;
}

bool EditorSceneNode::IsComposition() const
{
  return _composition;
}

void EditorSceneNode::SetComposition(bool composition)
{
  _composition = composition;
}

void EditorSceneNode::Change()
{
  emit Changed (this);
}

